using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.UIElements;

namespace XFFSM
{
    [CustomEditor(typeof(FSMController))]
    public class FSMControllerInspector : Editor
    {

        private FSMController controller => target as FSMController;

        private SerializedProperty script = null;

        private SerializedProperty resetOnDisable = null;

        private ReorderableList controllerList = null;

        private SerializedProperty _runtimeFSMControllerLayer;
        private SerializedProperty _runtimeFSMController;

        private GUIContent empty;

        private bool foldout = true;

        private void OnEnable()
        {
            script = serializedObject.FindProperty("m_Script");
            resetOnDisable = serializedObject.FindProperty("resetOnDisable");
            _runtimeFSMControllerLayer = serializedObject.FindProperty("_runtimeFSMControllerLayer");

            _runtimeFSMController = serializedObject.FindProperty("_runtimeFSMController");
        }

        public override void OnInspectorGUI()
        {
            if (controller == null) return;

            // 兼容逻辑 
            if (_runtimeFSMControllerLayer.arraySize == 0 && _runtimeFSMController.arraySize > 0) 
            {
                for (int i = 0; i < _runtimeFSMController.arraySize; i++)
                {
                    SerializedProperty property = _runtimeFSMController.GetArrayElementAtIndex(i);

                    if (property == null || property.objectReferenceValue == null) 
                        continue;
                     
                    int index = _runtimeFSMControllerLayer.arraySize;
                    _runtimeFSMControllerLayer.InsertArrayElementAtIndex(index);
                    SerializedProperty layer = _runtimeFSMControllerLayer.GetArrayElementAtIndex(index);
                    SerializedProperty name = layer.FindPropertyRelative("name");
                    SerializedProperty controller = layer.FindPropertyRelative("controller");

                    name.stringValue = string.Format("Layer {0}",i);
                    controller.objectReferenceValue = property.objectReferenceValue;
                } 

                // 清空
                _runtimeFSMController.ClearArray();

                serializedObject.ApplyModifiedProperties();
            }
            

            EditorGUI.BeginDisabledGroup(true);
            EditorGUILayout.PropertyField(script);
            EditorGUI.EndDisabledGroup();

            serializedObject.Update();

            if (controllerList == null) 
            {
                controllerList = new ReorderableList(serializedObject,_runtimeFSMControllerLayer);
                controllerList.headerHeight = 0;
                controllerList.drawElementCallback = ElementCallbackDelegate;
                controllerList.onAddCallback = AddCallbackDelegate;

                // 添加和移除用一样的
                controllerList.onCanAddCallback = CanAddCallbackDelegate;
                controllerList.onCanRemoveCallback = CanAddCallbackDelegate;
            }

            foldout = EditorGUILayout.BeginFoldoutHeaderGroup(foldout,"RuntimeFSMControllers");
            if (foldout)
                controllerList.DoLayoutList();

            EditorGUILayout.EndFoldoutHeaderGroup();
            // 
            EditorGUILayout.PropertyField(resetOnDisable);

            serializedObject.ApplyModifiedProperties();
        }


        private void ElementCallbackDelegate(Rect rect, int index, bool isActive, bool isFocused) 
        {
            if (index < 0 || index >= controllerList.serializedProperty.arraySize)
                return;

            EditorGUI.BeginDisabledGroup(Application.isPlaying);

            SerializedProperty property = controllerList.serializedProperty.GetArrayElementAtIndex(index);


            SerializedProperty name = property.FindPropertyRelative("name"); 
            SerializedProperty controller = property.FindPropertyRelative("controller");

            rect.width /= 2;

            string name_value = name.stringValue;
            EditorGUI.BeginChangeCheck();
            name_value = EditorGUI.DelayedTextField(rect, name_value);
            if (EditorGUI.EndChangeCheck()) 
            {
                // 名称改变
                if (IsContainName(name_value))
                {
                    EditorWindow.focusedWindow.ShowNotification(new GUIContent(string.Format("名称:{0}已经存在!", name_value)));
                }
                else 
                {
                    // 保存名称
                    name.stringValue = name_value;
                    name.serializedObject.ApplyModifiedProperties();
                }
            }

            rect.x += rect.width;

            if (empty == null)
                empty = new GUIContent();
            EditorGUI.PropertyField(rect, controller, empty); 

            EditorGUI.EndDisabledGroup();

            

        }

        private bool IsContainName(string name) 
        {
            foreach (var item in controller.RuntimeFSMControllerLayers)
            {
                if(item.name == name) return true;
            }

            return false;
        }


        private void AddCallbackDelegate(ReorderableList list) 
        {
            int index = list.serializedProperty.arraySize;
            list.serializedProperty.InsertArrayElementAtIndex(index);
            SerializedProperty property = list.serializedProperty.GetArrayElementAtIndex(index);

            SerializedProperty name = property.FindPropertyRelative("name"); 
            name.stringValue = GetLayerName();  
            name.serializedObject.ApplyModifiedProperties(); 
        }

        private bool CanAddCallbackDelegate(ReorderableList list) 
        {
            return !Application.isPlaying;
        }


        private string GetLayerName() {

            int index = 0;
            string name = string.Empty ;

            do
            {
                name = string.Format("Layer {0}", index);
                index++;
            } while (IsContainName(name));

            return name;

        }

    }
}

